#ifndef _TAGFS_MAP_H_
#define _TAGFS_MAP_H_

#include "tagfs_file.h"
#include "tagfs_node.h"

#include <vector>

class TagFS_Map
{
	public:
		void init(TagFS_Node*);

		uint64_t addFile(TagFile);
		uint64_t getFileCount();
		TagFile getFile(uint64_t);
		TagFile getFile(std::string);
		void updateFile(uint64_t, TagFile);
		void updateFile(std::string, TagFile);
		uint64_t getFID(std::string);
		void rmvFile(uint64_t);
		void rmvFile(std::string);

		void addTag(std::string, uint64_t);
		void rmvTag(std::string, uint64_t);
		std::list<std::string> getTags(uint64_t);
		void addTag(std::string, std::string);
		void rmvTag(std::string, std::string);
		std::list<std::string> getTags(std::string);
		std::list<uint64_t> tagFIDs(std::string);
		std::list<uint64_t> tagFIDs();

		void writeMaps();
		void print();

		struct MapMap
		{
			std::vector<uint64_t> file;
			uint8_t curFile;
			std::vector<uint64_t> tag;
			uint8_t curTag;
		};
	
	private:
		TagFS_Node* nodes;
		MapMap mapMap;
		
		std::map<uint64_t, TagFile> fileMap;
		std::map<std::string, uint64_t> reverseFileMap;
		uint32_t fileMapSize;

		std::map<std::string, std::pair<uint64_t, std::list<uint64_t> > > tagMap;
		uint32_t tagMapSize;

		uint32_t tagMapSizeCalc(std::map<std::string, std::pair<uint64_t, std::list<uint64_t> > > *map);
		uint32_t fileMapSizeCalc(std::map<uint64_t, TagFile> *map);

		void reserveFileNodes(std::map<uint64_t, TagFile>*);

		uint32_t calcTag(std::pair<std::string, std::pair<uint64_t, std::list<uint64_t> > >*);
		uint8_t  calcInt(uint64_t);

		uint8_t  encodeInt(uint64_t i, char* out);
		uint64_t decodeInt(char* data, uint8_t i);
		std::pair<uint64_t, int> writeData(uint64_t integer, uint8_t intbytes, uint64_t node, char* buf, uint16_t* bufpos);
		std::pair<uint64_t, int> writeData(std::string string, uint64_t node, char* buf, uint16_t* bufpos);

		void read(MapMap* map);
		void write(MapMap* map);

		void read(uint64_t nextNode, std::map<uint64_t, TagFile>* map);
		void write(uint64_t nextNode, std::map<uint64_t, TagFile>* map);

		void read(uint64_t nextNode, std::map<std::string, std::pair<uint64_t, std::list<uint64_t> > >* map);
		void write(uint64_t nextNode, std::map<std::string, std::pair<uint64_t, std::list<uint64_t> > >* map);
};

#endif
